home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Newswatcher 2.0b22 / NW Source / Source / apputil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-02  |  14.9 KB  |  312 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     apputil.c
  4.  
  5.     This reusable module contains utility routines for finding and running helper
  6.     applications.
  7.     
  8.     Adapted from DTS sample code "SignatureToApp" and "LaunchWithDoc"
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <string.h>
  13. #include <Aliases.h>
  14. #include <AppleEvents.h>
  15. #include <Folders.h>
  16. #include <Processes.h>
  17. #include <stdio.h>
  18.  
  19. #include "def.h"
  20. #include "apputil.h"
  21. #include "memutil.h"
  22. #include "fileutil.h"
  23. #include "strutil.h"
  24. #include "resutil.h"
  25.  
  26.  
  27.  
  28. /*----------------------------------------------------------------------------
  29.     FindRunningAppBySignature 
  30.     
  31.     Find a running app given its signature.
  32.     
  33.     Entry:    sig = signature of app.
  34.             
  35.     Exit:    function result = error code.
  36.                 = procNotFound if not running.
  37.             *fSpec = file spec of app. 
  38.             *psn = process serial number of running app.
  39. ----------------------------------------------------------------------------*/
  40.  
  41. static OSErr FindRunningAppBySignature (OSType sig, FSSpec *fSpec,
  42.     ProcessSerialNumber *psn)
  43. {
  44.     OSErr err = noErr;
  45.     ProcessInfoRec info;
  46.     
  47.     psn->highLongOfPSN = 0;
  48.     psn->lowLongOfPSN  = kNoProcess;
  49.     while (true) {
  50.         err = GetNextProcess(psn);
  51.         if (err != noErr) return err;
  52.         info.processInfoLength = sizeof(info);
  53.         info.processName = nil;
  54.         info.processAppSpec = fSpec;
  55.         err = GetProcessInformation(psn, &info);
  56.         if (err != noErr) return err;
  57.         if (info.processSignature == sig) return noErr;
  58.     }
  59. }
  60.  
  61.  
  62.  
  63. /*----------------------------------------------------------------------------
  64.     VolHasDesktopDB 
  65.     
  66.     Check to see if a volume supports the new desktop database.
  67.     
  68.     Entry:    vRefNum = vol ref num of volumn
  69.             
  70.     Exit:    function result = error code.
  71.             *hasDesktop = true if volume has the new desktop database.
  72. ----------------------------------------------------------------------------*/
  73.  
  74. static OSErr VolHasDesktopDB (short vRefNum, Boolean *hasDesktop)
  75. {
  76.     HParamBlockRec pb;
  77.     GetVolParmsInfoBuffer info;
  78.     OSErr err = noErr;
  79.     
  80.     pb.ioParam.ioCompletion = nil;
  81.     pb.ioParam.ioNamePtr = nil;
  82.     pb.ioParam.ioVRefNum = vRefNum;
  83.     pb.ioParam.ioBuffer = (Ptr)&info;
  84.     pb.ioParam.ioReqCount = sizeof(info);
  85.     err = PBHGetVolParmsSync(&pb);
  86.     *hasDesktop = err == noErr && (info.vMAttrib & (1L << bHasDesktopMgr)) != 0;
  87.     return err;
  88. }
  89.  
  90.  
  91.  
  92. /*----------------------------------------------------------------------------
  93.     FindAppOnVolume 
  94.     
  95.     Find an application on a volume.
  96.     
  97.     Entry:    sig = application signature.
  98.             vRefNum = vol ref num
  99.             
  100.     Exit:    function result = error code
  101.                 = afpItemNotFound if app not found on vol.
  102.             *file = file spec for application on volume.
  103. ----------------------------------------------------------------------------*/
  104.  
  105. static OSErr FindAppOnVolume (OSType sig, short vRefNum, FSSpec *file)
  106. {
  107.     DTPBRec pb;
  108.     OSErr err = noErr;
  109.     short ioDTRefNum, i;
  110.     FInfo fInfo;
  111.     FSSpec candidate;
  112.     unsigned long lastModDateTime, maxLastModDateTime;
  113.  
  114.     memset(&pb, 0, sizeof(DTPBRec));
  115.     pb.ioCompletion = nil;
  116.     pb.ioVRefNum = vRefNum;
  117.     pb.ioNamePtr = nil;
  118.     err = PBDTGetPath(&pb);
  119.     if (err != noErr) return err;
  120.     ioDTRefNum = pb.ioDTRefNum;
  121.  
  122.     memset(&pb, 0, sizeof(DTPBRec));
  123.     pb.ioCompletion = nil;
  124.     pb.ioIndex = 0;
  125.     pb.ioFileCreator = sig;
  126.     pb.ioNamePtr = file->name;
  127.     pb.ioDTRefNum = ioDTRefNum;
  128.     err = PBDTGetAPPLSync(&pb);
  129.     
  130.     if (err == fnfErr || err == paramErr) return afpItemNotFound;
  131.     if (err != noErr) return err;
  132.  
  133.     file->vRefNum = vRefNum;
  134.     file->parID = pb.ioAPPLParID;
  135.     
  136.     err = FSpGetFInfo(file, &fInfo);
  137.     if (err == noErr) return noErr;
  138.     
  139.     i = 1;
  140.     maxLastModDateTime = 0;
  141.     while (true) {
  142.         memset(&pb, 0, sizeof(DTPBRec)); 
  143.         pb.ioCompletion = nil;
  144.         pb.ioIndex = i;
  145.         pb.ioFileCreator = sig;
  146.         pb.ioNamePtr = candidate.name;
  147.         pb.ioDTRefNum = ioDTRefNum;
  148.         err = PBDTGetAPPLSync(&pb);
  149.         if (err != noErr) break;
  150.         candidate.vRefNum = vRefNum;
  151.         candidate.parID = pb.ioAPPLParID;
  152.         err = GetLastModDateTime(file, &lastModDateTime);
  153.         if (err == noErr) {
  154.             if (lastModDateTime > maxLastModDateTime) {
  155.                 maxLastModDateTime = lastModDateTime;
  156.                 *file = candidate;
  157.             }
  158.         }
  159.         i++;
  160.     }
  161.     
  162.     return maxLastModDateTime > 0 ? noErr : afpItemNotFound;
  163. }
  164.  
  165.  
  166.  
  167. /*----------------------------------------------------------------------------
  168.     FindAppFromSig 
  169.     
  170.     Find an application given its signature.
  171.     
  172.     Entry:    sig = application signature
  173.     
  174.     Entry:    running = nil to skip check for running app and just do
  175.                 a desktop database search for the disk file.
  176.             
  177.     Exit:    function result = error code.
  178.                 = fnfErr if app not found
  179.             *fSpec = file spec of application.
  180.             *running = true if app is running.
  181.             *psn = process serial number of app if running.
  182. ----------------------------------------------------------------------------*/
  183.  
  184. OSErr FindAppFromSig (OSType sig, FSSpec *fSpec, Boolean *running,
  185.      ProcessSerialNumber *psn)
  186. {
  187.     OSErr err = noErr;
  188.     short sysVRefNum, vRefNum, index;
  189.     Boolean hasDesktopDB;
  190.  
  191.     if (running != nil) {
  192.         err = FindRunningAppBySignature(sig, fSpec, psn);
  193.         *running = true;
  194.         if (err == noErr) return noErr;
  195.         *running = false;
  196.         if (err != procNotFound) return err;
  197.     }
  198.     err = GetSysVolume(&sysVRefNum);
  199.     if (err != noErr) return err;
  200.     vRefNum = sysVRefNum;
  201.     index = 0;
  202.     while (true) {
  203.         if (index == 0 || vRefNum != sysVRefNum) {
  204.             err = VolHasDesktopDB(vRefNum, &hasDesktopDB);
  205.             if (err != noErr) return err;
  206.             if (hasDesktopDB) {
  207.                 err = FindAppOnVolume(sig, vRefNum, fSpec);
  208.                 if (err != afpItemNotFound) return err;
  209.             }
  210.         }
  211.         index++;
  212.         err = GetIndVolume(index, &vRefNum);
  213.         if (err == nsvErr) return fnfErr;
  214.         if (err != noErr) return err;
  215.     }
  216. }
  217.  
  218.  
  219.  
  220. /*----------------------------------------------------------------------------
  221.     FindAppNameFromSig 
  222.     
  223.     Find an application name given its signature.
  224.     
  225.     Entry:    sig = application signature
  226.             
  227.     Exit:    function result = error code.
  228.                 = fnfErr if app not found
  229.             name = application name.
  230. ----------------------------------------------------------------------------*/
  231.  
  232. OSErr FindAppNameFromSig (OSType sig, StringPtr name)
  233. {
  234.     FSSpec fSpec;
  235.     OSErr err = noErr;
  236.     
  237.     err = FindAppFromSig(sig, &fSpec, nil, nil);
  238.     if (err != noErr) return err;
  239.     CopyPascalString(name, fSpec.name);
  240.     return noErr;
  241. }
  242.  
  243.  
  244.  
  245. /*----------------------------------------------------------------------------
  246.     LaunchAppWithDoc 
  247.     
  248.     Launch an application with an initial open document event.
  249.     
  250.     Entry:    running = true if application is running, in which case
  251.                 it is sent the odoc event.
  252.             appSpec = file spec of application.
  253.             *psn = process serial number of app if it is running.
  254.             docSpec = file spec of document.
  255.             launchFileFlags = file flags.
  256.             launchControlFlags = control flags.
  257.             
  258.     Exit:    function result = error code.
  259. ----------------------------------------------------------------------------*/
  260.  
  261. OSErr LaunchAppWithDoc (Boolean running, FSSpec *appSpec, ProcessSerialNumber *psn,
  262.     FSSpec *docSpec, unsigned short launchFileFlags, unsigned short launchControlFlags)
  263. {
  264.     ProcessSerialNumber thePSN;
  265.     LaunchParamBlockRec launchThis;
  266.     AEDesc target = {0, nil};
  267.     AEDesc docDesc = {0, nil};
  268.     AEDesc launchDesc = {0, nil};
  269.     AEDescList theList = {0, nil};
  270.     AliasHandle withThis = nil;
  271.     AppleEvent theEvent = {0, nil};
  272.     AppleEvent theReply = {0, nil};
  273.     OSErr err = noErr;
  274.     Boolean autoParamValue = false;
  275.  
  276.     if (running) thePSN = *psn;
  277.     err = AECreateDesc(typeProcessSerialNumber, &thePSN, sizeof(thePSN), &target); 
  278.     if (err != noErr) goto exit;
  279.     err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &target,
  280.         kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
  281.     if (err != noErr) goto exit;
  282.     err = AECreateList(nil, 0, false, &theList);
  283.     if (err != noErr) goto exit;
  284.     err = NewAlias(nil, docSpec, &withThis);
  285.     if (err != noErr) goto exit;
  286.     MyHLock(withThis);
  287.     err = AECreateDesc(typeAlias, (Ptr)*withThis, MyGetHandleSize(withThis), 
  288.         &docDesc);
  289.     if (err != noErr) goto exit;
  290.     MyHUnlock(withThis);
  291.     err = AEPutDesc(&theList, 0, &docDesc);
  292.     if (err != noErr) goto exit;
  293.     err = AEPutParamDesc(&theEvent, keyDirectObject, &theList);
  294.     if (err != noErr) goto exit;
  295.     if (running) {
  296.         err = AESend(&theEvent, &theReply, kAENoReply, kAENormalPriority, kNoTimeOut,
  297.             nil, nil);
  298.         if (err != noErr) goto exit;
  299.         if ((launchControlFlags & launchDontSwitch) == 0) {
  300.             err = SetFrontProcess(psn);
  301.             if (err != noErr) goto exit;
  302.         }
  303.     } else {
  304.         err = AECoerceDesc(&theEvent, typeAppParameters, &launchDesc);
  305.         if (err != noErr) goto exit;
  306.         MyHLock(theEvent.dataHandle);
  307.         launchThis.launchAppSpec = appSpec;
  308.         launchThis.launchAppParameters = (AppParametersPtr)*launchDesc.dataHandle;
  309.         launchThis.launchBlockID = extendedBlock;
  310.         launchThis.launchEPBLength = extendedBlockLen;
  311.         launchThis.launchFileFlags = launchFileFlags;